home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d7
/
commdrvr.arc
/
RS232.INC
< prev
next >
Wrap
Text File
|
1988-04-11
|
19KB
|
533 lines
page
;***********************************************************
;** **
;** Device Driver for RS232 communications **
;** Copyright (C) Texas Instruments 1986 **
;** Author: Greg Haley **
;** **
;** THIS SOURCE CODE MAY BE DISTRIBUTED AND MODIFIED **
;** ONLY IF THE ORIGINAL COPYRIGHT AND AUTHOR CREDITS **
;** REMAIN INTACT. **
;** **
;** Project Start Date: 09/09/86 **
;** **
;** Re: 10/14/86 by Greg Haley **
;** Added more delays (jmp $+2) for more tolerant **
;** timing. Also increased stacks to 80 words for **
;** Business Pro compatibility. **
;** **
;** Re: 10/15/86 by Greg Haley **
;** The COMM chip is no longer initialized on every **
;** write request. **
;** **
;** Re: 10/23/86 by Greg Haley **
;** Added code to block interrupts while setting up **
;** and restoring the stack. **
;** **
;** Re: 11/07/86 by Greg Haley **
;** Added option to echo RS232 I/O to the CRT. **
;** **
;** Re: 11/13/86 by Greg Haley **
;** Save SI and AX when calling DOS fast write. **
;** Changed SAR's and SAL's to SHR's and SHL's. **
;** Added keyboard input in parallel with RS232 input. **
;** **
;** Re: 11/20/86 by Greg Haley **
;** Modified I/O channel commands so that a more **
;** standard structure could be used, and to make it **
;** easier to add new commands in the future. Also, **
;** all machine dependent code was moved to a seperate **
;** file to allow new machines to be added much more **
;** easily. **
;** **
;** Re: 12/29/86 by Greg Haley **
;** Fixed bug in XON-XOFF busy handling where XON **
;** was not sent to reset the busy condition. **
;** **
;***********************************************************
cr equ 13
lf equ 10
fast_write equ 29h ; DOS INT for fast CRT write
com1_tbl: ;header for device
dw -1
dw -1
dw 1100000000000000B ; CHAR device with I/O control
dw strategy
dw entry
db 'AUX ' ; Device name to use
; command jump table
cmdtbl:
dw init
dw exit
dw exit
dw ioctl_in
dw read
dw nd_read
dw input_status
dw input_flush
dw write
dw write
dw output_status
dw exit
dw ioctl_out
dw exit
dw exit
dw exit
dw exit
oldss dw 0 ; Old SS reg
oldsp dw 0 ; Old SP reg
dw 80 dup (?) ; New stack
e_stack label word
ptrsav dd 0 ; DOS cmd block pointer
init_once db 0 ; flag for init
echo_in db 0 ; Echo input to console flag
echo_out db 0 ; Echo output to console flag
key_in db 0 ; Parallel keyboard input flag
dcw_len db 0 ; DCW (0) or Length (not 0) mode
page
;***********************************************************
;** Device Driver Entry **
;***********************************************************
cmdlen = 0 ;length of this command
unit = 1 ;sub unit specifier
cmd = 2 ;command code
status = 3 ;status
media = 13 ;media descriptor
trans = 14 ;transfer address
count = 18 ;count of blocks or characters
start = 20 ;first block to transfer
;***********************************************************
;** Strategy Routine **
;***********************************************************
stratp proc far
strategy:
mov word ptr cs:[ptrsav],bx
mov word ptr cs:[ptrsav+2],es
ret
stratp endp
;***********************************************************
;** Entry Routine **
;***********************************************************
entry:
cli ; disable ints
mov cs:word ptr oldss,ss
mov cs:word ptr oldsp,sp
mov sp,cs
mov ss,sp
mov sp,offset e_stack
sti ; enable ints
push si
push ax
push cx
push dx
push di
push bp
push ds
push es
push bx
lds bx,cs:[ptrsav] ;get pointer to i/o packet
mov cx,word ptr ds:[bx].count ;cx = count
mov al,byte ptr ds:[bx].cmd ; al = command
cbw
mov si,offset cmdtbl
add si,ax
add si,ax
cmp al,16
ja cmderr
les di,dword ptr ds:[bx].trans
push cs
pop ds
cld
assume ds:code
jmp word ptr [si] ;go do command
page
;***********************************************************
;** Device Driver Exit **
;***********************************************************
bus$exit: ;device busy exit
mov ah,00000011b
jmp short done
cmderr:
mov al,3 ;unknown command error
err$exit:
mov ah,10000001b ;mark error return
jmp short done
exitp proc far
exit:
mov ax,0000000100000000b
done:
lds bx,cs:[ptrsav]
mov word ptr [bx].status,ax ;mark operation complete
pop bx
pop es
pop ds
pop bp
pop di
pop dx
pop cx
pop ax
pop si
; restore stack
cli ; disable ints
mov ss,cs:word ptr oldss
mov sp,cs:word ptr oldsp
sti ; enable ints
ret ;restore regs and return
exitp endp
page
;***********************************************************
;** Write Routine **
;** **
;** ES:DI contain xfer adrs on entry **
;** CX contains num chars to write **
;** **
;** **
;***********************************************************
write proc near
push es ; Move pointer to DS:SI
pop ds
mov si,di
mov dx,cs:word ptr send_buffer ; xmit port
send_chars:
lodsb ; al now has char
cmp cs:byte ptr echo_out,0 ; Echo output on?
jz no_echo_out ; No, skip
push si
push ax
int fast_write ; Yes, echo to console
pop ax
pop si
no_echo_out:
write_1:
cmp cs:byte ptr t_busy,0 ; Is device busy?
jne write_1 ; Yes, loop again
x_busy:
cmp cs:byte ptr xmit_busy,0 ; Is transmitter busy?
jne x_busy ; Yes, wait for it
out dx,al
mov cs:byte ptr xmit_busy,1 ; We're busy now
loop send_chars ; look for more chars
jmp exit
write endp
page
;***********************************************************
;** Non Destructive Read Routine **
;** **
;** On entry, ES points to buffer segment **
;***********************************************************
nd_read proc near
mov di,13 ; point to byte buffer
cmp cs:byte ptr key_in,0 ; Look for keyboard input?
jz nd_read_0 ; No, skip
push cx
push di
call k_ready ; Is a char waiting?
pop di
pop cx
jz nd_read_0 ; No, skip
stosb ; Yes, store it
jmp exit ; We're done
nd_read_0:
cmp cs:word ptr rq_len,0 ; Any chars in receive buffer?
jnz nd_read_1 ; Yes, continue
mov ah,00000011b ; Set busy & done
jmp done ; We're done
nd_read_1:
mov bx,offset rqueue ; Get queue ptr
mov dx,cs:word ptr rq_tail
add bx,dx ; point at char
mov al,byte ptr[bx] ; al now has char
cmp cs:byte ptr echo_in,0 ; Echo input on?
jz no_echo_in ; No, skip
push si
push ax
int fast_write ; Yes, echo to console
pop ax
pop si
no_echo_in:
stosb ; store char in buffer
jmp exit
nd_read endp
page
;***********************************************************
;** Get Input Status **
;***********************************************************
input_status proc near
cmp cs:byte ptr key_in,0 ; Look for keyboard input?
jz in_stat_0 ; No, skip
call k_ready ; Is a char waiting?
jnz xit_in_stat ; Yes, exit
in_stat_0:
cmp cs:word ptr rq_len,0 ; Any chars in receive buffer?
jnz xit_in_stat ; Yes, continue
mov ah,00000011b ; No, set busy & done
jmp done ; We're done
xit_in_stat:
jmp exit ; Normal exit code
input_status endp
page
;***********************************************************
;** Flush Input Buffer **
;***********************************************************
input_flush proc near
mov cs:word ptr rq_head,0 ; Head = 0
mov cs:word ptr rq_tail,0 ; Tail = 0
mov cs:word ptr rq_len,0 ; make queue length 0
jmp exit ; Normal exit code
input_flush endp
page
;***********************************************************
;** Get Output Status **
;***********************************************************
output_status proc near
cmp cs:byte ptr t_busy,0 ; Are we busy?
je xit_out_stat ; No, continue
mov ah,00000011b ; Set busy & done
jmp done ; We're done
xit_out_stat:
jmp exit ; Normal exit code
output_status endp
page
;***********************************************************
;** Read Routine **
;** **
;** ES:DI contain xfer adrs on entry **
;** CX contains num chars requested **
;***********************************************************
read proc near
cmp cs:byte ptr key_in,0 ; Look for keyboard input?
jz read_0 ; No, skip
push cx
push di
call k_ready ; Is a char waiting?
pop di
pop cx
jz read_0 ; No, skip
mov cx,1
call update_count
push di
call k_read ; Get char from keyboard
pop di
stosb
jmp exit ; We're done
read_0:
mov ax,cs:word ptr rq_len ; Any chars in recv buffer?
or ax,ax
jnz read_1 ; Yes, continue
xor cx,cx ; No, return 0 chars received
call update_count
jmp exit ; We're done
read_1:
; figure out how many chars to get
cmp ax,cx ; More than DOS buffer?
jg read_2 ; Yes, CX already has count
mov cx,ax ; No, only send what we have
read_2:
call update_count ; update chars received
mov bx,offset rqueue ; Get queue ptr
mov dx,cs:word ptr rq_tail
read_3:
add bx,dx ; point at char
mov al,byte ptr[bx] ; al now has char
cmp cs:byte ptr echo_in,0 ; Echo input on?
jz not_echo_in ; No, skip
int fast_write ; Yes, echo to console
not_echo_in:
stosb ; store char in buffer
inc dx
and dx,recv_limit ; wrap if >= limit
mov cs:word ptr rq_tail,dx ; update tail
dec cs:word ptr rq_len ; Adjust queue length
loop read_3 ; Loop again
; reset busy if we can
cmp cs:word ptr rq_len,not_busy_len ; Room for more chars?
jg read_4 ; No, skip
mov cs:byte ptr r_busy,0 ; Yes, reset busy
call send_xon ; Send XON char if needed
read_4:
jmp exit
read endp
page
;***********************************************************
;** Write I/O Control Channel **
;** **
;** ES:DI contain xfer adrs on entry **
;** CX contains count **
;***********************************************************
ioctl_out proc near
push es ; Move pointer to DS:SI
pop ds
mov si,di
cmp cx,2 ; Is it a DCW?
je ioo_1 ; Yes, continue
cmp cx,1 ; Is it a CSB?
jz ioo_nc0 ; Yes, continue
jmp exit ; No, exit
ioo_nc0:
lodsb ; Yes, get the byte
push cs ; DS = CS
pop ds
mov ah,al ; Update echo output
and ah,00100000b
mov echo_out,ah
mov ah,al ; Update echo input
and ah,01000000b
mov echo_in,ah
mov ah,al ; Update keyboard input
and ah,10000000b
mov key_in,ah
mov ah,al ; Update DCW/LEN mode
and ah,00000100b
mov dcw_len,ah
test al,00000001b ; Drop RS232 signals?
jnz ioo_nc1 ; No, skip
call de_init ; Yes, disconnect
mov byte ptr dcw_len,0 ; Reset to DCW mode
ioo_nc1:
test al,00000010b ; Flush input buffer?
jz ioo_nc2 ; No, skip
jmp input_flush ; Yes, go flush it
ioo_nc2:
jmp exit ; exit
ioo_1:
lodsw ; get DCW in AX
; make ds = cs
push cs
pop ds
; check for serial device
test ah,80h ; Serial device?
jnz ioo_2 ; Yes, continue
jmp exit ; No, exit
ioo_2:
call set_dcw ; Go set DCW
mov word ptr dcw,ax ; Save new DCW
call init_comm ; init comm chip
jmp exit
ioctl_out endp
page
;***********************************************************
;** Read I/O Control Channel **
;** **
;** ES:DI contain xfer adrs on entry **
;***********************************************************
ioctl_in proc near
cmp cx,2 ; Is it a word?
je is_2byte ; Yes, go get it
cmp cx,1 ; Is it a byte?
jne ioi_xit ; No, exit
xor al,al ; Clear status byte
or al,cs:byte ptr m_stat ; Update current modem status
or al,cs:echo_out ; Update echo output
or al,cs:echo_in ; Update echo input
or al,cs:key_in ; Update keyboard input
stosb ; and pass it to DOS
jmp exit
is_2byte:
cmp cs:byte ptr dcw_len,0 ; DCW mode?
jz ioi_1 ; Yes, get DCW
mov ax,cs:rq_len ; No, get receive queue length
jmp short ioi_2
ioi_1:
mov ax,cs:dcw ; Get DCW
ioi_2:
stosw ; and pass it to DOS
ioi_xit:
jmp exit
ioctl_in endp
page
;***********************************************************
;** Return Number of Chars Processed **
;** **
;** CX contains number of characters processed **
;***********************************************************
update_count proc near
push ds
push bx
lds bx,cs:[ptrsav] ;get pointer to i/o packet
mov word ptr ds:[bx].count,cx ;cx = count
pop bx
pop ds
ret
update_count endp